/*
 * @Author: yanjikun
 * @Date: 2022-04-21 14:32:13
 * @LastEditors: yanjikun
 * @LastEditTime: 2022-05-06 15:07:06
 * @Description: file content
 */

import { isFunction } from '@/utils/is'
import { ConfigProvider, Modal } from 'ant-design-vue'
import { modalProps } from 'ant-design-vue/lib/modal/Modal'
import { omit } from 'lodash'
import { computed, defineComponent, PropType, ref, unref, watch } from 'vue'
import { useConfigProvider } from '../useConfigProvider'
import { HookModalProps } from './types'

export type MyModalInstance = InstanceType<typeof MyModal> & {
  setProps: (props: HookModalProps) => void
}
export const MyModal = defineComponent({
  props: {
    ...modalProps(),
    content: {
      type: [String, Function] as PropType<string | JSX.Element | (() => JSX.Element)>,
    },
    visible: {
      type: Boolean as PropType<boolean>,
    },
    closeModal: {
      type: Function as PropType<() => void>,
    },
    isAppChild: {
      type: Boolean as PropType<boolean>,
      default: true,
    },
  },
  setup(props, { attrs, expose }) {
    const confirmLoading = ref<boolean>(false)
    const getConfigProvider = useConfigProvider()
    const propsRef = ref({ ...props, ...attrs })
    const getProps = computed(() => {
      return { ...props, ...attrs, ...unref(propsRef) }
    })
    const bindValues = computed(() => {
      const _props = unref(getProps)
      return {
        ...omit(_props, ['onCancel', 'onOk']),
        visible: _props.visible,
        confirmLoading: confirmLoading.value,
        onCancel: handleCancel,
        onOk: handleConfirm,
      }
    })

    const setVisible = (visible: boolean) => {
      propsRef.value.visible = visible
    }

    const setProps = (props: HookModalProps) => {
      propsRef.value = {
        ...unref(getProps),
        ...props,
      }
    }

    watch(
      () => propsRef.value.visible,
      (val) => {
        Object.is(val, false) && props.closeModal?.()
      },
    )
    const handleConfirm = async (e: MouseEvent) => {
      confirmLoading.value = true
      try {
        await unref(getProps)?.onOk?.(e)
        setVisible(false)
      } catch (error) {
        return Promise.reject(error)
      } finally {
        confirmLoading.value = false
      }
    }
    const handleCancel = async (e: MouseEvent) => {
      await unref(getProps)?.onCancel?.(e)
      setVisible(false)
    }
    expose({
      setProps,
    })
    return () => {
      const _props = unref(getProps)
      const { content, isAppChild } = _props
      const Content = isFunction(content) ? content() : content
      return isAppChild ? (
        <Modal {...unref(bindValues)}>{Content}</Modal>
      ) : (
        <ConfigProvider {...getConfigProvider}>
          <Modal {...unref(bindValues)}>{Content}</Modal>
        </ConfigProvider>
      )
    }
  },
})
